package com.kha.listone.util.xml;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.kha.listone.common.model.SettingsModel;
import com.kha.listone.locale.LocaleConstants;
import com.kha.listone.util.Globals;

/**
 * Class in Charge of http connectivity and xml parsing
 */
public class SettingsXMLParser extends DefaultHandler implements
		com.kha.listone.util.operation.Operation {

	private String tempVal = null;

	private boolean isDone = false;

	public SettingsXMLParser() {

	}

	private InputStream getInputStream() {
		InputStream input = null;

		try {
			FileConnection fc = (FileConnection) Connector
					.open(Globals.XML_SETTINGS_FILE_PATH);
			if (!fc.exists()) {
				fc.create();
				return null;
			}
			input = fc.openInputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return input;
	}

	/**
	 * Starts parsing the received XML file using a SAXParser
	 */
	public void loadXML(InputStream input) {
		if (input == null){
			Globals.settingListOne = new SettingsModel();
			return;
		}
		SAXParser parser;
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			parser = factory.newSAXParser();

			InputSource fis = new InputSource(input);
			parser.parse(fis, this);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * Callback invoked when a start tag is loaded
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attributes
	 * @throws org.xml.sax.SAXException
	 */
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {

		if (qName.equalsIgnoreCase(Globals.TAG_SETTINGS)) {
			if (Globals.settingListOne == null) {
				Globals.settingListOne = new SettingsModel();
			}
			tempVal = "";
		}

	}

	/**
	 * Callback invoked when an end tag is found
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 *            Nombre de la etiqueta
	 * @throws org.xml.sax.SAXException
	 */
	public void endElement(String uri, String localName, String qName)
			throws SAXException {

		if (qName.equalsIgnoreCase(Globals.TAG_SETTING_DATEFORMAT)) {
			Globals.settingListOne.setDateFormat(Short.parseShort(tempVal));
		} else if (qName.equalsIgnoreCase(Globals.TAG_SETTING_LANGUAGE)) {
			Globals.settingListOne.setLanguage(Short.parseShort(tempVal));
			Globals.APP_LOCALE = (Globals.settingListOne.getLanguage() == SettingsModel.LANG_EN ? LocaleConstants.locales.EN
					: LocaleConstants.locales.VI);
		} else if (qName.equalsIgnoreCase(Globals.TAG_SETTING_SYNCTIME)) {
			Globals.settingListOne.setSyncTime(Integer.parseInt(tempVal));
		} else if (qName.equalsIgnoreCase(Globals.TAG_HAVE_DROPBOX)) {
			Globals.HAVE_DROPBOX = (Short.parseShort(tempVal) == 1 ? true
					: false);
		} else if (qName.equalsIgnoreCase(Globals.TAG_DROPBOX_USERNAME)) {
			Globals.DROPBOX_USERNAME = tempVal;
		} else if (qName.equalsIgnoreCase(Globals.TAG_DROPBOX_PASSWORD)) {
			Globals.DROPBOX_PASSWORD = tempVal;
		}
	}

	/**
	 * Callback invoked when the tag contains a text. Text is saved according to
	 * the tag being analyzed as the callback does not pass any reference to the
	 * current tag a global variable currentTag is used to store the value. Data
	 * is saved in the current visit
	 * 
	 * @param ch
	 * @param start
	 * @param length
	 * @throws org.xml.sax.SAXException
	 */
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String chars = new String(ch, start, length).trim();
		if (chars.length() > 0) {
			tempVal = chars;
		}
	}

	public void execute() {
		loadXML(getInputStream());
		isDone = true;
	}

	public boolean isDone() {
		return isDone;
	}

	public void setDone(boolean isDone) {
		this.isDone = isDone;
	}
}